package com.report;

import java.util.*;
import java.util.stream.Collectors;

public class DynamicGroupMerger {

    /**
     * 核心合并方法
     *
     * @param data               原始数据
     * @param mapping            映射规则（如{"张三":"银行存款"}）
     * @param groupByColumnIndex 分组依据列下标（如0代表第一列）
     * @param skipColumns        跳过的前导列数（如2）
     */
    public static List<List<String>> mergeData(List<List<String>> data, Map<String, String> mapping, int groupByColumnIndex, int skipColumns) {
        // 1. 应用映射规则（仅修改分组依据列）
        applyMapping(data, mapping, groupByColumnIndex);

        // 2. 按指定列分组
        Map<String, List<List<String>>> groupedData = new LinkedHashMap<>();
        for (List<String> row : data) {
            String groupKey = row.get(groupByColumnIndex);
            groupedData.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(row);
        }

        // 3. 合并每组数据
        return groupedData.values().stream()
                .map(group -> mergeGroup(group, groupByColumnIndex, skipColumns))
                .collect(Collectors.toList());
    }

    // 优化：仅修改分组依据列的值
    private static void applyMapping(List<List<String>> data, Map<String, String> mapping, int groupByColumnIndex) {
        if (mapping == null) return;
        for (List<String> row : data) {
            String originalValue = row.get(groupByColumnIndex);
            if (mapping.containsKey(originalValue)) {
                // 只修改分组依据列的值
                row.set(groupByColumnIndex, mapping.get(originalValue));
            }
        }
    }

    // 合并单组数据（保留原始列结构）
    private static List<String> mergeGroup(List<List<String>> group, int groupByColumnIndex, int skipColumns) {
        int colCount = group.get(0).size();
        List<String> mergedRow = new ArrayList<>(colCount);

        // 1. 复制分组依据列的值（不修改其他列）
        for (int i = 0; i < colCount; i++) {
            if (i == groupByColumnIndex) {
                mergedRow.add(group.get(0).get(i)); // 分组列用首行值
            } else {
                mergedRow.add(""); // 其他列先占位
            }
        }

        // 2. 处理数值列（跳过前导列和分组列）
        for (int colIdx = skipColumns; colIdx < colCount; colIdx++) {
            if (colIdx == groupByColumnIndex) continue; // 跳过分组列

            int sum = 0;
            boolean hasValue = false;
            for (List<String> row : group) {
                String val = row.get(colIdx);
                if (!val.isEmpty()) {
                    try {
                        sum += Integer.parseInt(val);
                        hasValue = true;
                    } catch (NumberFormatException ignored) {
                        // 非数值保留首次出现的值
                        if (mergedRow.get(colIdx).isEmpty()) {
                            mergedRow.set(colIdx, val);
                        }
                    }
                }
            }
            if (hasValue) {
                mergedRow.set(colIdx, String.valueOf(sum));
            }
        }
        return mergedRow;
    }

    // 测试用例
    public static void main(String[] args) {
        // 测试数据（使用第三列作为分组依据）
        List<List<String>> data = Arrays.asList(
                Arrays.asList("A", "库存现金", "1", "1", "id1"),
                Arrays.asList("B", "银行存款", "1", "1", "id2"),
                Arrays.asList("C", "张三", "2", "", "id3"),
                Arrays.asList("B", "李四", "", "3", "id4")  // 此处分组列=B，自动归入B组
        );

        // 映射配置（张三→银行存款）
        Map<String, String> mapping = new HashMap<>();
        mapping.put("张三", "银行存款");
        mapping.put("李四", "银行存款");

        // 执行合并：用第0列分组，跳过前1列
        List<List<String>> result = mergeData(data, mapping, 1, 2);

        // 验证：B组合并了李四的数值
        result.forEach(row -> System.out.println(String.join(" | ", row)));
        /* 输出：
          A | 库存现金 | 1 | 1 | id1
          B | 银行存款 | 1 | 4 | id2  // 李四的数值3合并到B组
          C | 张三     | 2 |   | id3 → 映射后变为"银行存款"，但分组仍用C列值
        */
    }
}